package org.huntaway.lucene.demo.util;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.huntaway.kernel.NutException;
import org.huntaway.lucene.base.BaseIndex;
import org.huntaway.lucene.bean.LuceneBean;

import com.chenlb.mmseg4j.analysis.MMSegAnalyzer;

public class LuceneUtil {
	Map<String, LuceneBean> luceneBeanMap = new HashMap<String, LuceneBean>();
	Map<String, Directory> dirMap = new HashMap<String, Directory>();
	Map<String, IndexWriter> indexWriterMap = new HashMap<String, IndexWriter>();

	// Map<String, BaseDocument> documentMap = new HashMap<String,
	// BaseDocument>();

	public static Analyzer getAnalyzer() {
		return new MMSegAnalyzer();
		// return new StandardAnalyzer(Version.LUCENE_33);
	}

	public IndexWriterConfig newIndexWriterConfig() {
		return new IndexWriterConfig(Version.LUCENE_33, getAnalyzer());
	}

	public static IndexWriter buildWriter(String indexDir,
			IndexWriterConfig indexWriterConfig) throws CorruptIndexException,
			LockObtainFailedException, IOException {
		return new IndexWriter(FSDirectory.open(new File(indexDir)),
				indexWriterConfig);
	}

	public IndexWriter buildWriter(String indexDir, boolean create)
			throws CorruptIndexException, LockObtainFailedException,
			IOException {
		IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_33,
				getAnalyzer());
		if (create) {
			// Create a new index in the directory, removing any
			// previously indexed documents:
			iwc.setOpenMode(OpenMode.CREATE);
		} else {
			// Add new documents to an existing index:
			iwc.setOpenMode(OpenMode.CREATE_OR_APPEND);
		}
		return new IndexWriter(buildDirectory(indexDir), iwc);
	}

	public Directory buildDirectory(String indexDir) throws IOException {
		try {
			return FSDirectory.open(new File(indexDir));
		} catch (IOException e) {
			throw e;
		}
	}

	public IndexWriter buildWriter(Directory directory, boolean create)
			throws CorruptIndexException, LockObtainFailedException,
			IOException {
		IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_33,
				getAnalyzer());
		if (create) {
			// Create a new index in the directory, removing any
			// previously indexed documents:
			iwc.setOpenMode(OpenMode.CREATE);
		} else {
			// Add new documents to an existing index:
			iwc.setOpenMode(OpenMode.CREATE_OR_APPEND);
		}
		return new IndexWriter(directory, iwc);
	}

	public Directory buildRawDirectory() {
		return new RAMDirectory();
	}

	public void buildWriter(LuceneBean luceneBean, boolean create)
			throws CorruptIndexException, LockObtainFailedException,
			IOException {
		luceneBeanMap.put(luceneBean.getName(), luceneBean);
		Directory dirItem = buildRawDirectory();
		IndexWriter indexWriterItem = buildWriter(dirItem, create);
		dirMap.put(luceneBean.getName(), dirItem);
		indexWriterMap.put(luceneBean.getName(), indexWriterItem);
	}

	protected void addDocument(File file) throws CorruptIndexException,
			IOException, NutException {
		if (DocFilter.filterFile(file)) {
			logln("ignore " + file);
			return;
		}
		logln("adding " + file);
		List<Map.Entry<String, LuceneBean>> luceneLst = new ArrayList<Map.Entry<String, LuceneBean>>(
				luceneBeanMap.entrySet());
		for (int i = 0; i < luceneLst.size(); i++) {
			LuceneBean itemBean = (LuceneBean) luceneLst.get(i);
			// if(itemBean.getName().endsWith(suffix))
			if (!itemBean.isIndex()) {
				return;
			} else {
				// indexWriterMap.get(itemBean.getName()).addDocument(doc)
			}
		}
		if (file.getName().endsWith(".text")) {
			// textWriter.addDocument(new TextDocument().document(file));
		}
		if (file.getName().endsWith(".java")) {
			// javaWriter.addDocument(new JavaDocument().document(file));
		}
		if (file.getName().endsWith(".xml")) {
			// xmlWriter.addDocument(new XmlDocument().document(file));
		}
		// writer.addDocument(new FileDocument().document(file));
		// throw new NutException("This code is not be run.....");
	}

	protected void logln(String str) {
		System.out.println(str);
	}

	/**
	 * @param luceneBean
	 * @return
	 */
	public IndexWriter getIndexWriter(LuceneBean luceneBean) {
		return indexWriterMap.get(luceneBean.getName());
	}

	public void setWriter(LuceneBean luceneBean, boolean create)
			throws CorruptIndexException, LockObtainFailedException,
			IOException {
		buildRawDir(luceneBean);
		buildIndexWriter(luceneBean,create);
		Directory writerDir = buildDirectory(BaseIndex.INDEX_DIR
				+ luceneBean.getName());
		dirMap.put(luceneBean.getName(), writerDir);
	}

	public void commitWriter(LuceneBean lucene, boolean create) {
		try {
			IndexWriter rawWriter = indexWriterMap.get(lucene.getName());
			rawWriter.commit();
			IndexWriter indexWriter = buildWriter(dirMap.get(lucene.getName()),
					create);
			indexWriter.addIndexes(dirMap.get("raw" + lucene.getName()));
			indexWriter.close();
			rebuildIndexWriter(lucene);			
		} catch (CorruptIndexException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private void rebuildIndexWriter(LuceneBean lucene) throws CorruptIndexException, LockObtainFailedException, IOException {
		rebuildRawDir(lucene);
		buildIndexWriter(lucene,false);
	}

	private void buildIndexWriter(LuceneBean lucene, boolean create) throws CorruptIndexException, LockObtainFailedException, IOException {
		IndexWriter indexWriterItem = buildWriter(dirMap.get("raw" + lucene.getName()), create);
		indexWriterMap.put(lucene.getName(), indexWriterItem);		
	}

	private void rebuildRawDir(LuceneBean lucene) {
		dirMap.remove("raw" + lucene.getName());
		buildRawDir(lucene);
	}

	private void buildRawDir(LuceneBean lucene) {
		Directory dirItem = buildRawDirectory();
		dirMap.put("raw" + lucene.getName(), dirItem);		
	}

	public void closeWriter(LuceneBean lucene, boolean create) {
		try {
			IndexWriter rawWriter = indexWriterMap.get(lucene.getName());
			rawWriter.close();
			IndexWriter indexWriter = buildWriter(dirMap.get(lucene.getName()),
					create);
			indexWriter.addIndexes(dirMap.get("raw" + lucene.getName()));
			indexWriter.close();
		} catch (CorruptIndexException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}
